package com.ilxqx.framework.system.util;

import com.ilxqx.framework.system.exception.SystemException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;

import javax.persistence.Id;
import java.lang.reflect.Field;

/**
 * 实体检测工具类
 * @author venus
 */
@Slf4j
public final class EntityCheckingUtils {

    /**
     * 检测实体对象主键
     * @param entity 实体对象
     * @param isNull 主键是否为空
     * @param <T> 实体泛型
     */
    private static <T> void checkPrimaryKey(T entity, boolean isNull) {
        Field[] fields = entity.getClass().getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(Id.class)) {
                field.setAccessible(true);
                try {
                    if (isNull) {
                        Assert.isNull(field.get(entity), "实体对象主键必须为NULL");
                    } else {
                        Assert.notNull(field.get(entity), "实体对象主键不能为NULL");
                    }
                    return;
                } catch (IllegalAccessException e) {
                    log.error("判断实体主键时，反射访问实体主键值时出现异常，具体异常为：{}", e);
                    throw new SystemException("判断实体主键时，反射访问实体主键值时出现异常");
                }
            }
        }
        throw new IllegalArgumentException("实体对象主键不存在");
    }

    /**
     * 判断实体对象主键是否为空
     * @param entity 实体对象
     * @param <T> 实体泛型
     */
    public static <T> void checkPrimaryKeyIsNull(T entity) {
        EntityCheckingUtils.checkPrimaryKey(entity, true);
    }

    /**
     * 判断实体对象主键是否不为空
     * @param entity 实体对象
     * @param <T> 实体泛型
     */
    public static <T> void checkPrimaryKeyNotNull(T entity) {
        EntityCheckingUtils.checkPrimaryKey(entity, false);
    }

    /**
     * 判断一个集合中所有实体对象的主键是否都为空
     * @param entities 实体对象集合
     * @param <T> 实体泛型
     */
    public static <T> void checkAnyEntityPrimaryKeyIsNull(Iterable<T> entities) {
        entities.forEach(entity -> EntityCheckingUtils.checkPrimaryKey(entity, true));
    }

    /**
     * 判断一个集合中所有的实体对象的主键是否都不为空
     * @param entities 实体对象集合
     * @param <T> 实体泛型
     */
    public static <T> void checkAnyEntityPrimaryKeyNotNull(Iterable<T> entities) {
        entities.forEach(entity -> EntityCheckingUtils.checkPrimaryKey(entity, false));
    }

}
